home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************/
- /* Added exiterr() for terminal errors to prevent SGML.MSG errors. */
- /******************************************************************************/
- #include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
- /******************************************************************************/
- /* ENTDEF: Process an entity definition and return the pointer to it.
- The entity text must be in permanent storage.
- There is no checking to see if the entity already exists;
- the caller must have done that.
- */
- PECB entdef(
- UNCH *ename, /* Entity name (with length and EOS). */
- UNCH estore, /* Entity storage class. */
- union etext *petx) /* Ptr to entity text union. */
- {
- PECB p;
-
- p = (PECB)hin((THASH)etab, ename, hash(ename, ENTHASH), ENTSZ);
- memcpy((UNIV)&p->etx, (UNIV)petx, ETEXTSZ);
- p->estore = estore;
- #ifndef FINAL
- if (etrace) traceecb("ENTDEF", p);
- #endif
- return(p);
- }
- /******************************************************************************/
- /* ENTFIND: If an entity exists, return ptr to its ecb.
- Return NULL if it is not defined.
- */
- PECB entfind(
- UNCH *ename) /* Entity name (with length and EOS). */
- {
- PECB p;
-
- p = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH));
- #ifndef FINAL
- if (etrace && p) traceecb("ENTFIND", p);
- #endif
- return p;
- }
- /******************************************************************************/
- /* ENTREF: Process a general or parameter entity reference.
- If the entity is defined it returns the return code from ENTOPEN.
- It returns ENTUNDEF for undefined parameter entity references
- and for general entity references when defaulting is not allowed.
- Otherwise, it uses the default entity text.
- */
- int entref(
- UNCH *ename) /* Entity name (with length and EOS). */
- {
- PECB ecb; /* Entity control block. */
-
- /* Get the entity control block, if the entity has been defined. */
- if ((ecb = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH)))==0) {
- if ( ename[1]==lex.d.pero
- || ecbdeflt==0
- || (ecb = usedef(ename))==0 ) {
- sgmlerr(35, (struct parse *)0, ename+1, NULL);
- return(ENTUNDEF);
- }
- }
- return(entopen(ecb));
- }
- /******************************************************************************/
- /* ENTOPEN: Open a newly referenced entity.
- Increment the stack pointer (es) and initialize the new entry.
- Returns ENTSGI if entity is STARTGI, ENTEGI if it is ENDGI,
- ENTDATA if entity is CDATA or SDATA, ENTPI if it is PI,
- 0 if normal and all o.k.; <0 if not.
- */
- int entopen(
- struct entity *ecb) /* Entity control block. */
- {
- int i; /* Loop counter. */
-
- /* See if we have exceeded the entity nesting level. */
- if (es>=ENTLVL) {
- sgmlerr(34, (struct parse *)0, ecb->ename+1, NULL);
- return(ENTMAX);
- }
- /* If entity is an etd, pi, or data, return it without creating an scb. */
- switch (ecb->estore) {
- case ESS:
- etisw = 0;
- newetd = ecb->etx.e;
- return(ENTSGI);
- case ESE:
- newetd = ecb->etx.e;
- return(ENTEGI);
- case ESN:
- if (NEDCNID(ecb->etx.n)==0)
- sgmlerr(78,(struct parse *)0, NEDCN(ecb->etx.n)+1, ecb->ename+1);
- data = (UNCH *)ecb->etx.n;
- entdatsw = NDECONT;
- return(ENTDATA);
- case ESC:
- case ESX:
- if((datalen = *(ecb->etx.c) - 2)==0) return(0);
- data = ecb->etx.c+1;
- entdatsw = (ecb->estore==ESC) ? CDECONT : SDECONT;
- return(ENTDATA);
- case ESI:
- datalen = *(ecb->etx.c) - 2;
- data = ecb->etx.c+1;
- entpisw = 4;
- return(ENTPI);
- }
- /* If the same entity is already open, send msg and ignore it.
- Level 0 needn't be tested, as its entity name is always *DOC.
- */
- for (i = 0; ++i<=es;) if (scbs[i].ecb.enext==ecb) {
- sgmlerr(36, (struct parse *)0, ecb->ename+1, NULL);
- return(ENTLOOP);
- }
- /* Update SCB if entity trace is wanted in messages or entity is a file.
- (Avoid this at start when es==-1 or memory will be corrupted.)
- */
- if ((sw.swenttr || FILESW) && es>=0) scbset();
-
- /* Stack the new source control block (we know there is room). */
- ++es; /* Increment scbs index. */
- RCNT = CCO = RSCC = 0; /* No records or chars yet. */
- memcpy((UNIV)&ECB, (UNIV)ecb, (UNS)ENTSZ); /* Copy the ecb into the scb. */
- ECBPTR = ecb; /* Save the ecb pointer in scb.ecb.enext. */
- #ifndef FINAL
- if (etrace) traceecb("ENTOPEN", ECBPTR);
- #endif
-
- /* For memory entities, the read buffer is the entity text
- (after skipping past the length byte).
- The text starts at FBUF, so FPOS should be FBUF-1
- because it is bumped before each character is read.
- */
- if (ECB.estore<ESFM) {FPOS = (FBUF = ECB.etx.c+1)-1; return 0;}
-
- /* For file entities, suspend any open file and do first read. */
- fileopen(); /* Open new external file. */
- if (io.ipbrc<0) { /* If open not successful: */
- FPOS = FBUF-1; /* Clean CCNT for OPEN error msg.*/
- error(FILERR, 32, 0, ecb->ename+1, NULL);
- --es; /* Pop the stack. */
- return(ENTFILE);
- }
- filepend(es); /* Suspend any open file. */
- fileread(); /* First read of file must be ok.*/
- return 0;
- }
- /******************************************************************************/
- /* ENTGET: Get next record of entity (if there is one).
- Otherwise, close the file (if entity is a file) and
- pop the entity stack. If nothing else is on the stack,
- return -1 to advise the caller.
- */
- /*lint +fvr Returned value may be ignored. */
- int entget(void)
- /*lint -fvr Restore normal LINT processing. */
- {
- RSCC += (int)(CCO=(UNS)(FPOS-FBUF));
- /* Characters-in-record (ignore EOB/EOF). */
- tagctr += (int)CCO; /* Update tag length counter. */
- switch (*FPOS) {
- case EOBCHAR: /* End of file buffer: refill it. */
- fileread(); /* Read the file. */
- if (io.ipbrc>0) return (0); /* No errors: return. */
- readerr:
- error(FILERR, 31, 0, ENTITY+1, NULL);/* Treat error as EOF. */
- case EOFCHAR: /* End of file: close it. */
- fileclos(); /* Call SGMLIO to close file. */
- conterr:
- if (es==0) { /* Report if it is primary file. */
- FPOS = FBUF-1; /* Preserve CCNT for omitted end-tags. */
- return (-1);
- }
- case EOS: /* End of memory entity: pop the stack. */
- #ifndef FINAL
- if (etrace) traceecb("ENTPOP", ECBPTR);
- #endif
- --es; /* Pop the SCB stack. */
- if (FBUF) return (0); /* Return if not PEND file. */
- filecont(); /* Resume previous file. */
- if (io.ipbrc<0) { /* If CONT not successful: */
- error(FILERR, 94, 0, ENTITY+1, NULL);
- goto conterr;
- }
- fileread(); /* Read the file. */
- if (io.ipbrc<=0) goto readerr; /* If READ not successful: */
- if (delmscsw && es==0) /* End of DTD. */
- {delmscsw = 0; *rbufs = lex.d.msc;}
- return(0);
- }
- return(0); /* Avoid lint and TurboC warnings. */
- }
- /******************************************************************************/
- /* USEDEF: Use the default value for an entity reference.
- Returns the ECB for the defaulted entity.
- */
- PECB usedef(
- UNCH *ename) /* Entity name (with length and EOS). */
- {
- union etext etx; /* Save return from entgen. */
- PECB ecb; /* Entity control block. */
- PNE pne; /* Ptr to NDATA entity control block. */
- UNCH estore; /* Default entity storage type. */
-
- if ((estore = ecbdeflt->estore)<ESFM) /* Default is an internal string. */
- etx.c = ecbdeflt->etx.c;
- else {
- /* Move entity name into fpi. */
- memcpy(fpidf.fpinm, ename, (fpidf.fpinml = (char)*ename));
- if ((etx.x = entgen(&fpidf))==0) return (PECB)0;
- if (estore==ESN) {
- memcpy((UNIV)(pne=(PNE)rmalloc((UNS)NESZ)),(UNIV)ecbdeflt->etx.n,(UNS)NESZ);
- NEID(pne) = etx.x;
- etx.n = pne;
- }
- }
- if (sw.swrefmsg) sgmlerr(45, (struct parse *)0, ename+1, NULL);
- ++ds.ecbcnt;
- ecb = entdef(ename, estore, &etx);
- if (estore==ESN) NEENAME(pne) = ecb->ename;
- return(ecb);
- }
- /******************************************************************************/
- /* SCBSET: Set source control block to current location in the current entity.
- This routine is called by SGML when it returns to the text
- processor and by ERROR when it reports an error.
- */
- VOID scbset(void)
- {
- CC = *FPOS;
- CCO = (UNS)(FPOS+1-FBUF);
- return;
- }
- /******************************************************************************/
- /* ENTGEN: Call SGMLIO (FILENM) to generate an external id from an fpi.
- SGMLIO returns a ptr in io.ipbn to the xid in its memory.
- The pointer is zero if no valid identifier could be generated.
- ENTGEN returns a universal pointer because SGML does not need to
- look at the returned data; it is just saved to pass on to SGMLIO
- when the file is opened.
- */
- UNIV entgen(
- struct fpi *fpis) /* FPI structure. */
- {
- io.sgmles = es; /* Current SCBS level. */
- io.ipbn = (UNIV)fpis; /* FPI structure. */
- io.ipbtype = FILENM; sgmlio(&io); /* Generate fileid. */
- return(io.ipbn); /* Get its long ptr from IPB. */
- }
- /******************************************************************************/
- /* FILEOPEN: Call SGMLIO to open an external entity (file).
- The routine sets io.ipbn to the SGMLIO fcb pointer.
- */
- VOID fileopen(void) /* Open an external entity's file. */
- {
- io.sgmles = es; /* SCBS index for this file. */
- io.ipbn = ECB.etx.x; /* Ptr to DOS fileid in tp. */
- io.ipbtype = FILEOPEN; sgmlio(&io); /* Open the file. */
- SCBFCB = io.ipbn; /* Save SGMLIO fcb ptr. */
- }
- /******************************************************************************/
- /* FILEREAD: Call SGMLIO to read an open external entity (file).
- */
- VOID fileread(void) /* Read the current external entity's file. */
- {
- io.sgmles = es; /* SCBS index for this file. */
- io.ipbn = SCBFCB; /* Ptr to SGMLIO fcb. */
- io.ipbbuf = rbufs; /* Starting read position. */
- io.ipbtype = FILEREAD; sgmlio(&io); /* Read the file. */
- FPOS = (FBUF = io.ipbbuf)-1; /* Actual read buffer. */
- }
- /******************************************************************************/
- /* FILEPEND: Call SGMLIO to close an open external entity (file) temporarily.
- */
- VOID filepend( /* Close the current external entity's file. */
- int es) /* Local index to scbs. */
- {
- while (--es>=0) { /* Find last external file on stack. */
- if (!FILESW) continue; /* Not an external file. */
- FBUF = 0; /* Indicate pending file. */
- RSCC += (int)CCO; /* Update characters-in-record counter. */
- tagctr += (int)CCO; /* Update tag length counter. */
- io.sgmles = es; /* SCBS index for this file. */
- io.ipbn = SCBFCB; /* Ptr to SGMLIO fcb. */
- io.ipboff = CCO; /* Chars read in current block. */
- CCO = 0; /* So CCNT will be correct. */
- io.ipbtype = FILEPEND; /* Close the file. */
- sgmlio(&io); /* Call sgmlio. */
- return;
- }
- }
- /******************************************************************************/
- /* FILECONT: Call SGMLIO to reopen an external entity (file).
- */
- VOID filecont(void) /* Open an external entity's file. */
- {
- io.sgmles = es; /* SCBS index for this file. */
- io.ipbn = SCBFCB; /* Ptr to SGMLIO fcb. */
- io.ipbtype = FILECONT; sgmlio(&io); /* Open the file. */
- }
- /******************************************************************************/
- /* FILECLOS: Call SGMLIO to close an open external entity (file).
- */
- VOID fileclos(void) /* Close the current external entity's file. */
- {
- io.sgmles = es; /* SCBS index for this file. */
- io.ipbn = SCBFCB; /* Ptr to SGMLIO fcb. */
- io.ipbtype = FILECLOS; sgmlio(&io); /* Close the file. */
- }
- /******************************************************************************/
- /* ERROR: Interface to text processor SGML I/O services for error handling.
- */
- VOID error(
- UNS type, /* Type of error. */
- UNS number, /* Error number. */
- UNS errsp, /* Index to parse or declaration name. */
- UNCH *parm1, /* Error message parameters. */
- UNCH *parm2) /* Error message parameters. */
- {
- scbset(); /* Update location in source control block. */
- ie.errtype = type; /* Type of error: DOC FIL MD SYN. */
- ie.sgmles = es; /* Current level in scb stack. */
- ie.errnum = number; /* Error number. */
- ie.errsp = errsp; /* Index to parse or declaration name. */
- ie.eparm[0] = parm1; /* Parameter 1 ptr. */
- ie.eparm[1] = parm2; /* Parameter 2 ptr. */
- sgmlmsg(&ie);
- return;
- }
- /******************************************************************************/
- /* PTRSRCH: Find a pointer in a list and return its index.
- Search key must be on list as there is no limit test.
- This routine is internal only -- not for user data.
- */
- UNIV mdnmtab[MAXDCLS] = {
- syn.k.attlist,
- syn.k.doctype,
- syn.k.element,
- syn.k.entitee,
- syn.k.linktype,
- syn.k.link,
- syn.k.notation,
- syn.k.sgml,
- syn.k.shortref,
- syn.k.uselink,
- syn.k.usemap
- };
- UNIV pcbtab[MAXPCBS] = {
- (UNIV)&pcbconc,
- (UNIV)&pcbcone,
- (UNIV)&pcbconm,
- (UNIV)&pcbconr,
- (UNIV)&pcbetag,
- (UNIV)&pcbgrcm,
- (UNIV)&pcbgrcs,
- (UNIV)&pcbgrnm,
- (UNIV)&pcbgrnt,
- (UNIV)&pcblitc,
- (UNIV)&pcblitp,
- (UNIV)&pcblitr,
- (UNIV)&pcblitv,
- (UNIV)&pcbmd,
- (UNIV)&pcbmdc,
- (UNIV)&pcbmdi,
- (UNIV)&pcbmds,
- (UNIV)&pcbmsc,
- (UNIV)&pcbmsi,
- (UNIV)&pcbmsrc,
- (UNIV)&pcbpro,
- (UNIV)&pcbref,
- (UNIV)&pcbstag,
- (UNIV)&pcbval
- };
- UNS ptrsrch(
- UNIV ptrtab[],
- UNIV ptr)
- {
- UNS i;
-
- for (i = 0; ; ++i) {
- #ifndef FINAL
- if (dtrace) {
- if (ptrtab==pcbtab)
- tracemap(((struct parse *)ptr)->pname,
- ((struct parse *)ptrtab[i])->pname, (int)i);
- else tracemap(ptr, ((STRING)ptrtab[i])+1, (int)i);
- }
- #endif
- if (ptrtab[i]==ptr) return(i);
- }
- /*lint -unreachable There is no implied return at this point. */
- }
- /******************************************************************************/
- /* MDERR: Process errors for markup declarations.
- Prepare the special parameters that only exist for
- markup declaration errors.
- */
- VOID mderr(
- UNS number, /* Error number. */
- UNCH *parm1, /* Additional parameters (or NULL). */
- UNCH *parm2) /* Additional parameters (or NULL). */
- {
- UNS type = MDERR2; /* Assume no declaration subject. */
-
- ie.parmno = parmno; /* Parameter number. */
- if (subdcl) {
- type = MDERR;
- memcpy(ie.subdcl, subdcl, NAMELEN+1); /* Dcl subject identifier. */
- ie.subdcl[NAMELEN] = EOS; /* Truncate if lengthy. */
- }
- error(type, number, MAXPCBS+ptrsrch(mdnmtab, mdname), parm1, parm2);
- }
- /******************************************************************************/
- /* SGMLERR: Process errors for SGML parser.
- */
- VOID sgmlerr(
- UNS number, /* Error number. */
- struct parse *pcb, /* Current parse control block. */
- UNCH *parm1, /* Error message parameters. */
- UNCH *parm2) /* Error message parameters. */
- {
- if (!pcb) pcb = prologsw ? propcb : conpcb;
- error(DOCERR, number, ptrsrch(pcbtab, (UNIV)pcb), parm1, parm2);
- }
- /******************************************************************************/
- /* EXITERR: Process terminal errors for SGML parser.
- */
- VOID exiterr(
- UNS number, /* Error number. */
- struct parse *pcb) /* Current parse control block. */
- {
- if (!pcb) pcb = prologsw ? propcb : conpcb;
- error(EXITERR, number, ptrsrch(pcbtab, (UNIV)pcb), FPOS, NULL);
- }
- /******************************************************************************/
- /* SYNERR: Process syntax errors for SGML parser.
- */
- VOID synerr(
- UNS number, /* Error number. */
- struct parse *pcb) /* Current parse control block. */
- {
- error(DOCERR, number, ptrsrch(pcbtab, (UNIV)pcb), NULL, NULL);
- }
- /******************************************************************************/
-